﻿namespace DynamicPatterns.Tests
{
	using Microsoft.VisualStudio.TestTools.UnitTesting;
	using System;
	using System.Dynamic;

	[TestClass]
	public class DynamicsTests
	{
		[TestMethod]
		public void Snapshot()
		{
			var mock = new CounterMock();
			dynamic snapshot = Dynamics.Snapshot(mock);

			mock.Value++;

			Assert.AreEqual(0, snapshot.Value);
		}

		[TestMethod]
		[ExpectedException(typeof(ArgumentNullException))]
		public void Snapshot_ArgumentNull()
		{
			dynamic d = Dynamics.Snapshot(null);
		}

		[TestMethod]
		public void Proxy()
		{
			string mock = "Hello world!";
			dynamic proxy = Dynamics.Proxy(mock);
			Assert.AreEqual(12, proxy.Length);
		}


		[TestMethod]
		public void Combine()
		{
			dynamic combined = Dynamics.Combine(new { A = 1 }, new { B = 2 });
			Assert.AreEqual(1, combined.A);
			Assert.AreEqual(2, combined.B);
		}

		[TestMethod]
		[ExpectedException(typeof(ArgumentNullException))]
		public void Combine_ArgumentNull()
		{
			dynamic d = Dynamics.Combine(null);
		}

		[TestMethod]
		public void Multicast()
		{
			ChangeMock mock1 = new ChangeMock(), mock2 = new ChangeMock();
			Assert.IsFalse(mock1.Changed);
			Assert.IsFalse(mock2.Changed);

			dynamic multicast = Dynamics.Multicast(mock1, mock2);
			multicast.Change();

			Assert.IsTrue(mock1.Changed);
			Assert.IsTrue(mock2.Changed);
		}

		[TestMethod]
		[ExpectedException(typeof(ArgumentNullException))]
		public void Multicast_ArgumentNull()
		{
			dynamic d = Dynamics.Multicast(null);
		}

		[TestMethod]
		public void LoadBalance()
		{
			ChangeMock mock1 = new ChangeMock(), mock2 = new ChangeMock();
			Assert.IsFalse(mock1.Changed);
			Assert.IsFalse(mock2.Changed);

			dynamic loadBalancer = Dynamics.LoadBalance<ChangeMock>(mock1, mock2);
			
			loadBalancer.Change();
			Assert.IsTrue(mock1.Changed);

			loadBalancer.Change();
			Assert.IsTrue(mock2.Changed);
		}

		[TestMethod]
		[ExpectedException(typeof(ArgumentNullException))]
		public void LoadBalance_ArgumentNull()
		{
			dynamic d = Dynamics.LoadBalance<object>(null);
		}


		private class CounterMock
		{
			public int Value { get; set; }
		}

		private class ChangeMock
		{
			public bool Changed { get; set; }

			public void Change()
			{
				this.Changed = true;
			}
		}
	}
}
